package report

import (
	"bytes"
	"common/ipv6"
	"common/utils"
	"context"
	"encoding/json"
	"fmt"
	"go.uber.org/zap"
	"io"
	"net/http"
	"time"
)

type Config struct {
	ApiUrl    string        `help:"上报平台地址" default:"http://gongantest.guanjieai.com/airisk-tms/dcs/v1/sendHttpUrl"`
	ApiKey    string        `help:"上报平台key" default:"1c43j9uych1p4sqqi2d2f9vngjgnivnx"`
	CompanyId string        `help:"商户id" default:"1"`
	Timeout   time.Duration `help:"上报超时时间" default:"10s"`
	Internal  time.Duration `help:"上报间隔" default:"10m"`
}

type Service struct {
	config          *Config
	endpointAddress string
	port            int
	log             *zap.Logger
}

func NewService(addr string, port int, conf *Config, log *zap.Logger) *Service {
	return &Service{
		config:          conf,
		endpointAddress: addr,
		port:            port,
		log:             log,
	}
}

func (s *Service) Run(ctx context.Context) error {
	if err := s.request(ctx); err != nil {
		return err
	}
	return utils.RunTicker(ctx, s.config.Internal, func() error {
		return s.request(ctx)
	})
}

func (s *Service) request(ctx context.Context) error {
	runCtx, cancel := context.WithTimeout(ctx, s.config.Timeout)
	defer cancel()
	reportAddress := []string{}
	if s.endpointAddress == "" {
		reportAddress = append(reportAddress, fmt.Sprintf("http://%s:%d/default", fmt.Sprintf(ipv6.GetIPV4()), s.port))
	} else {
		reportAddress = append(reportAddress, s.endpointAddress)
	}
	body := map[string]any{
		"ListUrl":   reportAddress,
		"companyId": s.config.CompanyId,
	}
	res, _ := json.Marshal(body)
	req, err := http.NewRequestWithContext(runCtx, "POST", s.config.ApiUrl, bytes.NewBuffer(res))
	if err != nil {
		s.log.Error("http.NewRequestWithContext error", zap.Error(err))
		return nil
	}
	req.Header.Set("Authorization", s.config.ApiKey)
	req.Header.Set("companyId", s.config.CompanyId)
	req.Header.Set("Content-Type", "application/json;charset:utf-8")
	client := http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		s.log.Error("client.Do error", zap.Error(err))
		return nil
	}
	if resp.StatusCode == 200 {
		return nil
	}
	_b, _ := io.ReadAll(resp.Body)
	s.log.Debug("request", zap.String("status", resp.Status), zap.ByteString("req", res), zap.ByteString("resp", _b))
	return nil
}
